Passed
Push — main ( 31e2ff...254896 )
by Andrii
02:10
created

ctx.ts ➔ classNamer   A

Complexity

Conditions 3

Size

Total Lines 34
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 25
dl 0
loc 34
rs 9.28
c 0
b 0
f 0
cc 3
1
import type { Falsy, ToggleMap, ClassNamer, ClassNamed, ClassNamesMap, EmptyObject } from "./defs"
2
import {dehash, truthyKeys, wrapper} from "./core"
3
import { emptize } from "./utils"
4
5
emptize(classNamer)
6
7
//TODO no `className` - no first `true`
8
interface tClassNaming<
9
  ClassKeys extends string,
10
  withClassNames extends boolean | undefined
11
> {
12
  /**
13
   * @example classes(true) === props.className
14
   * @example classes({class1: true, class2: false}) === "class1"
15
   * @example classes("class3", false && "class4") === "class3"
16
   * @example classes(true, {class1: true, class2: false}, "class3", false && "class4") === `${props.className} class1 class3`
17
  */
18
 // Using overloads will make error not in certain argument but on all call - 'No overload found'
19
  (
20
    propagate_or_map_or_expression?: true | ToggleMap<ClassKeys> | ClassKeys | Falsy,
21
    map_or_expression?: (
22
      [Extract<typeof propagate_or_map_or_expression, true>] extends [never]
23
      ? never
24
      : ToggleMap<ClassKeys>
25
    ) | ClassKeys | Falsy,
26
    ...expressions: (ClassKeys | Falsy)[]
27
  ) : ClassNamed & (
28
    withClassNames extends true
29
    ? {classnames: ClassNamesMap<ClassKeys>}
30
    : EmptyObject
31
  ) 
32
}
33
34
export default classNamingCtx
35
36
/**
37
 * @example const classes = classNamingCtx(this.props)
38
 * @example const classes = classNamingCtx({className, classnames})
39
 * @example const classes = classNamingCtx({classnames})
40
 */
41
function classNamingCtx<
42
  ClassKeys extends string,
43
  withClassNames extends boolean|undefined
44
>(
45
  {classnames, className}: ClassNamer<ClassKeys>,
46
  options?: ClassNamerOptions<withClassNames>
47
) {
48
  return classNamer.bind({classnames, className, ...options}) as tClassNaming<ClassKeys, withClassNames>
49
}
50
51
type ClassNamerOptions<
52
  withClassNames extends undefined|boolean
53
> = Partial<{
54
  withClassNames: withClassNames
55
  // withSelf: boolean
56
}>
57
58
function classNamer<
59
  ClassKeys extends string,
60
  withClassNames extends boolean|undefined
61
>(
62
  this: Partial<ClassNamer<ClassKeys> & ClassNamerOptions<withClassNames>>,
63
  arg0?: true | ToggleMap<ClassKeys> | ClassKeys,
64
  arg1?: ToggleMap<ClassKeys> | ClassKeys,
65
  ...args: (ClassKeys | Falsy)[]
66
): ClassNamed & Partial<Pick<typeof this, "classnames">> {
67
  const {
68
    className: propagated,
69
    classnames,
70
    withClassNames,
71
    // withSelf
72
  } = this
73
  , withPropagation = arg0 === true
74
  , allowed: ClassKeys[] = truthyKeys(arg0 === true ? false : arg0)
75
  .concat(truthyKeys(arg1))
76
  //@ts-expect-error
77
  .concat(args)
78
  .filter<ClassKeys>(
79
    //@ts-expect-error
80
    Boolean
81
  )
82
  
83
  emptize(classnames)
84
85
  classnames && dehash(classnames, allowed)
86
    
87
  return wrapper(
88
    withPropagation && propagated,
89
    allowed,
90
    !withClassNames ? {} : {classnames}
91
  )
92
}